using FireStarter.Base;
using FireStarter.Base.BusinessObjectMerger;
using FireStarterModeller.BO;
using FireStarterModeller.Logic.MergeBusinessObjects;
using FireStarterModeller.Test.BO;
using NUnit.Framework;
using System.Linq;

namespace FireStarterModeller.Test.Logic.MergeBusinessObjects
{
    [TestFixture]
    public class TestMergeDMObjectID
    {
        [TestFixtureSetUp]
        public virtual void TestFixtureSetup()
        {
            TestUtilsLogic.SetupFixture();
        }
        [SetUp]
        public virtual void SetupTest()
        {
            TestUtilsLogic.SetupTest();
        }

        [Test]
        public void Test_MergeDMObjectIdentity_WithNoProps_ShouldUpdateOIdName()
        {
            //---------------Set up test pack-------------------
            IMergeBO<DMObjectIdentity> mergeOId = MergeableBORegistry.Instance.Resolve<DMObjectIdentity>();
            var fromOId = TestUtilsDMObjectIdentity.CreateUnsavedValidDMObjectIdentity();
            fromOId.IsObjectID = true;
            var toOId= new DMObjectIdentity {IsObjectID = false};
            //---------------Assert Precondition----------------
            Assert.IsTrue(fromOId.IsObjectID.GetValueOrDefault());
            Assert.IsFalse(toOId.IsObjectID.GetValueOrDefault());
            //---------------Execute Test ----------------------
            var mergedOId = mergeOId.MergeBOFrom(fromOId, toOId);
            //---------------Test Result -----------------------
            Assert.AreEqual(fromOId.IsObjectID, mergedOId.IsObjectID);
        }

        [Test]
        public void Test_MergeDMObjectIdentity_WithOIdProp_ShouldNotAffectTheOIdProp()
        {
            //---------------Set up test pack-------------------
            IMergeBO<DMObjectIdentity> mergeOId = MergeableBORegistry.Instance.Resolve<DMObjectIdentity>();
            var fromOId = TestUtilsDMObjectIdentity.CreateUnsavedValidDMObjectIdentity();
            var fromDMProp = fromOId.Properties[0];


            var toOId = new DMObjectIdentity();
            var toDMClass = TestUtilsDMClass.CreateUnsavedValidDMClass();
            toOId.Class = toDMClass;
            var toDMProp = toDMClass.CreateDMProp();
            toDMProp.PropertyName = fromDMProp.PropertyName;
            toOId.Properties.Add(toDMProp);

            //---------------Assert Precondition----------------
            Assert.AreEqual(1, fromOId.Properties.Count);
            Assert.AreEqual(1, toOId.Properties.Count);
            Assert.AreEqual(fromDMProp.PropertyName, toDMProp.PropertyName);
            Assert.AreNotSame(fromDMProp, toDMProp);
            //---------------Execute Test ----------------------
            DMObjectIdentity mergedOId = mergeOId.MergeBOFrom(fromOId, toOId);
            //---------------Test Result -----------------------
            Assert.AreEqual(1, mergedOId.Properties.Count);
            var mergedOIdProp = mergedOId.Properties[0];
            Assert.AreEqual(fromDMProp.PropertyName, mergedOIdProp.PropertyName);
            Assert.AreSame(toDMProp, mergedOIdProp);
        }
        [Test]
        public void Test_MergeDMObjectIdentity_WithOIdProp_WhenNOProp_ShouldLinkOIdPropWithDMProp()
        {
            //---------------Set up test pack-------------------
            IMergeBO<DMObjectIdentity> mergeOId = MergeableBORegistry.Instance.Resolve<DMObjectIdentity>();
            var fromOId = TestUtilsDMObjectIdentity.CreateUnsavedValidDMObjectIdentity();
            var fromOIdProp = fromOId.Properties[0]; 
            
            var toOId = new DMObjectIdentity();

            var toDMClass = TestUtilsDMClass.CreateUnsavedValidDMClass();
            toOId.Class = toDMClass;
            var toDMProp = toDMClass.CreateDMProp();
            toDMProp.PropertyName = fromOIdProp.PropertyName;

            //---------------Assert Precondition----------------
            Assert.AreEqual(1, fromOId.Properties.Count);

            Assert.AreEqual(0, toOId.Properties.Count);
            //---------------Execute Test ----------------------
            DMObjectIdentity mergedOId = mergeOId.MergeBOFrom(fromOId, toOId);
            //---------------Test Result -----------------------
            Assert.AreEqual(1, mergedOId.Properties.Count);
            var mergedOIdProp = mergedOId.Properties[0];
            Assert.AreSame(toDMProp, mergedOIdProp);
        }

        [Test]
        public void Test_MergeDMClass_WhenTOClassNoObjectID_ShouldCreateAndLinkOIDProps()
        {
            //---------------Set up test pack-------------------
            IMergeBO<DMClass> classMerger = MergeableBORegistry.Instance.Resolve<DMClass>();
            var fromOId = TestUtilsDMObjectIdentity.CreateUnsavedValidDMObjectIdentity();
            var fromClass = fromOId.Class;
            var fromOIdProp = fromOId.Properties[0];

            var toDMClass = TestUtilsDMClass.CreateUnsavedValidDMClass();
            var toDMProp = toDMClass.CreateDMProp();
            toDMProp.PropertyName = fromOIdProp.PropertyName;
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, fromOId.Properties.Count);
            Assert.IsNull(toDMClass.ObjectIdentity);
            //---------------Execute Test ----------------------
            DMClass mergedDMClass = classMerger.MergeBOFrom(fromClass, toDMClass);
            //---------------Test Result -----------------------
            DMObjectIdentity mergedOId = mergedDMClass.ObjectIdentity;
            Assert.IsNotNull(mergedOId);
            Assert.AreEqual(1, mergedOId.Properties.Count);
            var mergedOIdProp = mergedOId.Properties[0];
            Assert.AreEqual(fromOIdProp.PropertyName, mergedOIdProp.PropertyName);
            Assert.AreEqual(ChangeType.Add, ((IMergableBo)mergedOId).PendingChangeType);
        }

        [Test]
        public void Test_MergeObjectId_WhenIDPropNotOnClass_ShouldCreateOIDAndLinkPropName()
        {
            //---------------Set up test pack-------------------
            IMergeBO<DMClass> classMerger = MergeableBORegistry.Instance.Resolve<DMClass>();
            var fromOId = TestUtilsDMObjectIdentity.CreateUnsavedValidDMObjectIdentity();
            var fromClass = fromOId.Class;
            var fromOIdProp = fromOId.Properties[0];

            var toDMClass = TestUtilsDMClass.CreateUnsavedValidDMClass();
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, fromOId.Properties.Count);
            Assert.IsNull(toDMClass.ObjectIdentity);
            var toProperty = toDMClass.Properties.FirstOrDefault(property => property.PropertyName == fromOIdProp.PropertyName);
            Assert.IsNull(toProperty);

            Assert.AreEqual(0, toDMClass.Properties.Count);
            //---------------Execute Test ----------------------
            DMClass mergedDMClass = classMerger.MergeBOFrom(fromClass, toDMClass);
            //---------------Test Result -----------------------
            DMObjectIdentity mergedOId = mergedDMClass.ObjectIdentity;
            Assert.IsNotNull(mergedOId);
            Assert.AreEqual(1, mergedOId.Properties.Count);
            var mergedOIdProp = mergedOId.Properties[0];
            Assert.AreEqual(fromOIdProp.PropertyName, mergedOIdProp.PropertyName);
            Assert.AreEqual(ChangeType.Add, ((IMergableBo)mergedOId).PendingChangeType);
            Assert.AreEqual(1, toDMClass.Properties.Count, "ObjectIDProp should be added to class.");
            var findPropByName = toDMClass.FindPropByName(fromOIdProp.PropertyName);
            Assert.IsNotNull(findPropByName, "Created Prop should have correct prop name");
        }
    }
}